/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = zookeeper_core.c                                                 */
/*  NOTE      = TDS协议解析                                                   */
/*  DATE      = 2014/05/27 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#include "frservice_comm.h"
#include "zookeeper_core.h"
#include "zookeeper_common.h"
#include "zookeeper_request.h"
#include "zookeeper_response.h"
#include "config.h"

extern void *g_p_apm_context;

#define ZOOKEEPER_HASH_COUNT 100

/*******************************************************************************
*  FUNC     :  初始化私有Zookeeper session
*  ARGS     :  p_st_session(SQL Server私有session)
*  RTN      :  FR_SUCC       (normal)
*              FR_FAIL       (error)
*  NOTE     :
*******************************************************************************/
static int __zookeeper_init_private(L7_session *p_st_session)
{
    L7_fragment_zookeeper *p_st_fragment = NULL;              /* 分片包相关数据 */
    L7session_zookeeper  *p_st_zookeeper_conn = NULL;          /* 链接信息 */
    L7session_zookeeper_private *p_st_private_session = NULL; /* zookeeper私有session */
    Frhash_header *p_hash_header = NULL;

    /* 申请整个私有session结构的内存 */
    p_st_private_session = (L7session_zookeeper_private *)frmalloc(sizeof(L7session_zookeeper_private));
    if (p_st_private_session == NULL)
    {
        goto error;
    }
    memset(p_st_private_session, 0x00, sizeof(L7session_zookeeper_private));

    /* 申请链路信息结构内存 */
    p_st_zookeeper_conn = (L7session_zookeeper *)frmalloc(sizeof(L7session_zookeeper));
    if (p_st_zookeeper_conn == NULL)
    {
        goto error;
    }
    memset(p_st_zookeeper_conn, 0x00, sizeof(L7session_zookeeper));

    /* 申请分片包信息结构内存 */
    p_st_fragment = (L7_fragment_zookeeper *)frmalloc(sizeof(L7_fragment_zookeeper));
    if (p_st_fragment == NULL)
    {
        goto error;
    }
    memset(p_st_fragment, 0x00, sizeof(L7_fragment_zookeeper));

    /* 创建hash */
    p_hash_header = frhash2_create2(ZOOKEEPER_HASH_COUNT);
    if (p_hash_header == NULL)
    {
        goto error;
    }

    /* 设置初始化结构 */
    p_st_private_session->p_st_sess = p_st_zookeeper_conn;
    p_st_private_session->p_st_fragment = p_st_fragment;
    p_st_private_session->p_hash_header = p_hash_header;
    p_st_session->p_session_private = p_st_private_session;
    return FR_SUCC;

error:
    zookeeper_free((char **)(&p_st_private_session));
    zookeeper_free((char **)(&p_st_zookeeper_conn));
    zookeeper_free((char **)(&p_st_fragment));
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  取得完整的packet包
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_packet(入力packet信息)
            :  p_st_hash_report(保存Frreport_data)
*  RTN      :  FR_FAIL (true)
*              FR_SUCC (false)
*  NOTE     :  解析失败后需要释放p_st_private里的request/response/fragment信息
*******************************************************************************/
static int __zookeeper_set_analysis_data(Conntrack *p_st_conn
                                        , Apm_packet *p_st_packet
                                        , L7session_zookeeper_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_req_resp = 0;
    uint32_t u32_total_len = 0;
    int i_acl_len = 0;
    unsigned int ui_len = p_st_packet->ui_payload_len;
    char *p_data = p_st_packet->p_payload;
    L7_fragment_zookeeper *p_st_fragment = p_st_private->p_st_fragment;

    if (ui_len == 0)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得方向 */
    i_req_resp = frcap_get_cs_direction(p_st_conn, p_st_packet->src_ip
                                       , p_st_packet->src_port);
    /* 新数据包 */
    if (p_st_fragment->p_st_data == NULL)
    {
        /* 做成bytebuffer */
        p_st_fragment->p_st_data = bytebuff_creat();
        if (p_st_fragment->p_st_data == NULL)
        {
            frdbg("create bytebuff failed\n");
            return APM_L7_ANALYZE_FAIL;
        }
        i_ret = bytebuff_add(p_st_fragment->p_st_data, p_data, ui_len);
        if (i_ret != FR_SUCC)
        {
            frdbg("add data to bytebuff failed\n");
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得数据包总长度 */
        i_ret = bytebuff_get_int(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN
                                , &u32_total_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC || u32_total_len < ZOOKEEPER_XID_LEN + ZOOKEEPER_TYPE_LEN)
        {
            frdbg("get packet length failed\n");
            return APM_L7_ANALYZE_FAIL;
        }

        p_st_fragment->i_req_resp = i_req_resp;
        p_st_fragment->ui_total_len = u32_total_len + ZOOKEEPER_HEAD_LEN;
        /* 设置第一个分片包时间 */
        p_st_fragment->st_start_timestamp = p_st_packet->st_timestamp;
        /* 无其他分片包 */
        if (p_st_fragment->ui_total_len == ui_len)
        {
            /* 设置最后一个分片包时间 */
            p_st_fragment->st_end_timestamp = p_st_packet->st_timestamp;
            return APM_L7_ANALYZE_SUCC;
        }
        else if (u32_total_len + ZOOKEEPER_HEAD_LEN > ui_len)
        {
            return APM_L7_ANALYZE_TODO;
        }
        else /* 数据长度不匹配,但是有可能是订阅包，有多个 */
        {
            ui_len -= u32_total_len + ZOOKEEPER_HEAD_LEN;
            while (ui_len)
            {
                /* 跳过一段 */
                bytebuff_skip(p_st_fragment->p_st_data, u32_total_len);
                /* 长度不足 */
                if (bytebuff_remaining(p_st_fragment->p_st_data) < ZOOKEEPER_HEAD_LEN)
                {
                    bytebuff_setPosition(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN);
                    return APM_L7_ANALYZE_TODO;
                }
                i_ret = bytebuff_get_int(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN
                                        , &u32_total_len, BYTE_BIG_ENDIAN);
                if (i_ret != FR_SUCC || u32_total_len < ZOOKEEPER_XID_LEN + ZOOKEEPER_TYPE_LEN)
                {
                    frdbg("get packet length failed\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 到此结束 */
                if (u32_total_len + ZOOKEEPER_HEAD_LEN == ui_len)
                {
                    bytebuff_setPosition(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN);
                    p_st_fragment->st_end_timestamp = p_st_packet->st_timestamp;
                    return APM_L7_ANALYZE_SUCC;
                }
                else if (u32_total_len + ZOOKEEPER_HEAD_LEN > ui_len)
                {
                    bytebuff_setPosition(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN);
                    return APM_L7_ANALYZE_TODO;
                }
                else
                {
                    ui_len -= u32_total_len + ZOOKEEPER_HEAD_LEN;
                }
            }
            bytebuff_setPosition(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN);
            p_st_fragment->st_end_timestamp = p_st_packet->st_timestamp;
            return APM_L7_ANALYZE_SUCC;
        }
    }
    else
    {
        /* 判断数据包方向是否一致 */
        if (i_req_resp != p_st_fragment->i_req_resp)
        {
            frdbg("数据包方向不一致\n");
            zookeeper_init_curr_info(p_st_private);
            i_ret = __zookeeper_set_analysis_data(p_st_conn, p_st_packet, p_st_private);
            return i_ret;
        }
        else
        {
            if (bytebuff_length(p_st_fragment->p_st_data) + ui_len == p_st_fragment->ui_total_len)
            {
                i_ret = bytebuff_add(p_st_fragment->p_st_data, p_data, ui_len);
                if (i_ret != FR_SUCC)
                {
                    frdbg("add data to bytebuff failed\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                p_st_fragment->st_end_timestamp = p_st_packet->st_timestamp;
                return APM_L7_ANALYZE_SUCC;
            }
            else if (bytebuff_length(p_st_fragment->p_st_data) + ui_len < p_st_fragment->ui_total_len)
            {
                i_ret = bytebuff_add(p_st_fragment->p_st_data, p_data, ui_len);
                if (i_ret != FR_SUCC)
                {
                    frdbg("add data to bytebuff failed\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                return APM_L7_ANALYZE_TODO;
            }
            else /* 数据长度不匹配,但是有可能是订阅包，有多个 */
            {
                 i_ret = bytebuff_add(p_st_fragment->p_st_data, p_data, ui_len);
                 if (i_ret != FR_SUCC)
                 {
                     frdbg("add data to bytebuff failed\n");
                     return APM_L7_ANALYZE_FAIL;
                 }
                /* 跳过一段 */
                u32_total_len = p_st_fragment->ui_total_len - ZOOKEEPER_HEAD_LEN;
                bytebuff_skip(p_st_fragment->p_st_data, u32_total_len);
                while (bytebuff_remaining(p_st_fragment->p_st_data))
                {
                    /* 长度不足 */
                    if (bytebuff_remaining(p_st_fragment->p_st_data) < ZOOKEEPER_HEAD_LEN)
                    {
                        bytebuff_setPosition(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN);
                        return APM_L7_ANALYZE_TODO;
                    }
                    i_ret = bytebuff_get_int(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN
                                            , &u32_total_len, BYTE_BIG_ENDIAN);
                    if (i_ret != FR_SUCC || u32_total_len < ZOOKEEPER_XID_LEN + ZOOKEEPER_TYPE_LEN)
                    {
                        frdbg("get packet length failed\n");
                        return APM_L7_ANALYZE_FAIL;
                    }
                    i_acl_len = bytebuff_remaining(p_st_fragment->p_st_data);
                    /* 到此结束 */
                    if (u32_total_len == (uint32_t)i_acl_len)
                    {
                        bytebuff_setPosition(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN);
                        p_st_fragment->st_end_timestamp = p_st_packet->st_timestamp;
                        return APM_L7_ANALYZE_SUCC;
                    }
                    else if (u32_total_len + ZOOKEEPER_HEAD_LEN > (uint32_t)i_acl_len)
                    {
                        bytebuff_setPosition(p_st_fragment->p_st_data, ZOOKEEPER_HEAD_LEN);
                        return APM_L7_ANALYZE_TODO;
                    }
                    else
                    {
                        bytebuff_skip(p_st_fragment->p_st_data, u32_total_len);
                    }
                }
                 p_st_fragment->st_end_timestamp = p_st_packet->st_timestamp;
                 return APM_L7_ANALYZE_SUCC;
            }
        }
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  判断当前数据链路是否是zookeeper协议
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_packet(入力数据包)
*  RTN      :  APM_L7_IS_NO   (NO)
*              APM_L7_IS_YES  (YES)
*  NOTE     :
*******************************************************************************/
int zookeeper_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    int i_ret = FR_SUCC;
    int i_xid = 0;
    int i_type = 0;
    uint32_t u32_len = 0;
    uint32_t u32_xid = 0;
    uint32_t u32_type = 0;
    unsigned int ui_len = 0;
    char *p_data = NULL;
    Frbyte_Packet *p_st_data = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_packet->p_payload == NULL)
        return APM_L7_IS_NO;

    ui_len = p_st_packet->ui_payload_len;           /* packet数据长度 */
    p_data = p_st_packet->p_payload;                /* packet数据内容 */
    //printf("ui_len=[%d]\n", ui_len);
    if (ui_len < ZOOKEEPER_HEAD_LEN + ZOOKEEPER_XID_LEN + ZOOKEEPER_TYPE_LEN)
    {
        goto error;
    }

    /* 创建bytebuff */
    p_st_data = bytebuff_creat();
    if (p_st_data == NULL)
    {
        frdbg("Create bytebuff failed!\n");
        goto error;
    }
    i_ret = bytebuff_add(p_st_data, p_data, ui_len);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    /* 取得header length */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u32_len + 4 != ui_len)
    {
        goto error;
    }

    /* 取得XID */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_xid, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    i_xid = (int)u32_xid;

    /* 取得TYPE */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_type, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        goto error;
    }
    i_type = (int)u32_type;

    switch (i_type)
    {
        case ZOOKEEPER_PING_OP:
            if (i_xid != ZOOKEEPER_PING_XID)
            {
                goto error;
            }
            break;

        case ZOOKEEPER_SETAUTH_OP:
            if (i_xid != ZOOKEEPER_AUTH_XID)
            {
                goto error;
            }
            break;

        case ZOOKEEPER_SETWATCHES_OP:
            if (i_xid != ZOOKEEPER_SET_WATCHES_XID)
            {
                goto error;
            }
            break;

        case ZOOKEEPER_CLOSE_OP:
            if (bytebuff_remaining(p_st_data))
            {
                goto error;
            }
            break;

        case ZOOKEEPER_CREATE_OP:
            /* path */
            i_ret = zookeeper_skip_string(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            /* data */
            i_ret = zookeeper_skip_buffer(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            /* ACLs */
            i_ret = zookeeper_skip_acl_vector(p_st_data);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                goto error;
            }
            /* 正确的格式是后面没有其他数据 */
            if (bytebuff_remaining(p_st_data))
            {
                goto error;
            }
            break;

        case ZOOKEEPER_DELETE_OP:
            /* path */
            i_ret = zookeeper_skip_string(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            if (bytebuff_remaining(p_st_data) != ZOOKEEPER_INT_LEN)
            {
                goto error;
            }
            break;

        case ZOOKEEPER_EXISTS_OP:
        case ZOOKEEPER_GETDATA_OP:
        case ZOOKEEPER_GETCHILDREN_OP:
        case ZOOKEEPER_GETCHILDREN2_OP:
            /* path */
            i_ret = zookeeper_skip_string(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            if (bytebuff_remaining(p_st_data) != 1)
            {
                goto error;
            }
            break;

        case ZOOKEEPER_SETDATA_OP:
            /* path */
            i_ret = zookeeper_skip_string(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            /* data */
            i_ret = zookeeper_skip_buffer(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            if (bytebuff_remaining(p_st_data) != ZOOKEEPER_INT_LEN)
            {
                goto error;
            }
            break;

        case ZOOKEEPER_GETACL_OP:
        case ZOOKEEPER_SYNC_OP:
            i_ret = zookeeper_skip_string(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            if (bytebuff_remaining(p_st_data))
            {
                goto error;
            }
            break;

        case ZOOKEEPER_SETACL_OP:
            /* path */
            i_ret = zookeeper_skip_string(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            /* acl */
            i_ret = zookeeper_skip_acl_vector(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                goto error;
            }
            if (bytebuff_remaining(p_st_data) != ZOOKEEPER_INT_LEN)
            {
                goto error;
            }
            break;

        //case ZOOKEEPER_CHECK_OP:
        //case ZOOKEEPER_MULTI_OP:
        default:
            goto error;
    }

    bytebuff_free(&p_st_data);
    /* 设置方向 */
    if(frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip , p_st_packet->dst_port);
        if (i_ret != FR_SUCC)
        {
            frdbg("Set server ip and port failed!\n");
            return APM_L7_IS_NO;
        }
    }

    frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
    return APM_L7_IS_YES;

error:
    bytebuff_free(&p_st_data);
    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }
    return APM_L7_IS_NO;
}

/*******************************************************************************
*  FUNC     :  SQL Server的packet解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_packet(入力packet信息)
            :  p_st_hash_report(保存Frreport_data)
*  RTN      :  参照module.h
*  NOTE     :
*******************************************************************************/
int zookeeper_analysis(Conntrack *p_st_conn
                     , Apm_packet *p_st_packet
                     , Frhash_header *p_st_hash_report)
{
    int i_ret = FR_SUCC;
    int i_req_resp = FR_DIRECT_UNKNOWN;               /* 请求方向 */
    L7_session *p_st_session = NULL;                  /* L7session */
    L7session_zookeeper_private *p_st_private = NULL; /* zookeeper的私有数据 */

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
    {
        frdbg("Call frct_get_session failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /*
    * 如果入力p_st_packet是FIN包, 说明本次zookeeper的connection结束,
    * 释放本次session信息. 如果入力p_st_packet是SYN包,说明新的zookeeper的
    * connection开始了, 释放上次可能残留的session信息
    */
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN
        || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        //frdbg("FIN or SYN\n");
        /* 销毁所有相关本次zookeeper的connection的数据 */
        zookeeper_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }
    /* 本次链路的第一个有效packet包,创建链路 */
    if (p_st_session->p_session_private == NULL)
    {
        //frdbg("=======start parse zookeeper=========\n");
        /* 初始化SQL Server的私有数据 */
        i_ret = __zookeeper_init_private(p_st_session);
        if (i_ret != FR_SUCC)
        {
            frdbg("Call __zookeeper_init_private failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        /* 设置session ID */
        fruuid(p_st_session->arr_session_id);
    }
    p_st_private = (L7session_zookeeper_private *)p_st_session->p_session_private;

    /* 设置解析数据 */
    i_ret = __zookeeper_set_analysis_data(p_st_conn, p_st_packet, p_st_private);
    if (i_ret == APM_L7_ANALYZE_FAIL)
    {
        frdbg("set analysis data failed\n");
        zookeeper_init_curr_info(p_st_private);
        return APM_L7_ANALYZE_FAIL;
    }
    else if (i_ret == APM_L7_ANALYZE_TODO)
    {
        frdbg("more data\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得请求/响应方向 */
    i_req_resp = frcap_get_cs_direction(p_st_conn, p_st_packet->src_ip
                                       , p_st_packet->src_port);

    //frdbg("p_st_packet->ui_payload_len=[%d],i_req_resp=[%d]\n", p_st_packet->ui_payload_len, i_req_resp);
    /* 解析request */
    if (i_req_resp == FR_CLIENT_IP_PORT)
    {
        i_ret = zookeeper_parse_req(p_st_conn, p_st_private, p_st_hash_report);
    }
    /* 解析response */
    else if (i_req_resp == FR_SRV_IP_PORT)
    {
        i_ret = zookeeper_parse_resp(p_st_conn, p_st_private, p_st_hash_report);
    }

    /* 解析出错 */
    if (i_ret == APM_L7_ANALYZE_FAIL)
    {
        frdbg("Prase packet failed!\n");
        zookeeper_init_curr_info(p_st_private);
        return APM_L7_ANALYZE_FAIL;
    }

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  私有信息销毁
*  ARGS     :  p_private_session(zookeeper的私有session数据)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
int zookeeper_session_destroy(void *p_private_session)
{
    L7session_zookeeper_private *p_st_private = (L7session_zookeeper_private *)p_private_session;

    /* 判断session是否为空 */
    if (p_st_private == NULL)
    {
        return FR_SUCC;
    }

    /* 销毁session数据 */
    if (p_st_private->p_st_sess)
    {
        zookeeper_destroy_session(&(p_st_private->p_st_sess));
    }

    /* 销毁response数据 */
    if (p_st_private->p_st_resp)
    {
        zookeeper_destroy_resp(&p_st_private->p_st_resp);
    }

    /* 销毁分片数据 */
    if (p_st_private->p_st_fragment)
    {
        zookeeper_destroy_fragment(&p_st_private->p_st_fragment);
    }

    /* 销毁prepare数据 */
    frhash2_free2(p_st_private->p_hash_header, zookeeper_req_node_free);

    frfree(p_st_private);

    return FR_SUCC;
}
